package net.jonbuck.tassoo.ui.dialog;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;

import net.jonbuck.tassoo.model.AttachmentType;
import net.jonbuck.tassoo.ui.dialog.provider.AttachmentTypeContentProvider;
import net.jonbuck.tassoo.ui.dialog.provider.AttachmentTypeLabelProvider;
import net.jonbuck.tassoo.ui.util.CommonImages;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.ValidationStatusProvider;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.dialog.TitleAreaDialogSupport;
import org.eclipse.jface.databinding.dialog.ValidationMessageProvider;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;

/**
 * 
 * 
 * @since 1.0.0
 */
public class LaunchApplicationDialog extends TitleAreaDialog {

	/** ... TODO Javadoc ... */
	private DataBindingContext bindingContext;

	/** ... TODO Javadoc ... */
	private ArrayList<AttachmentType> launchApps;

	/** ... TODO Javadoc ... */
	private List list;

	/** ... TODO Javadoc ... */
	private String message;

	/** ... TODO Javadoc ... */
	private PropertyChangeSupport propertyChangeSupport =  new PropertyChangeSupport(this);

	/** ... TODO Javadoc ... */
	private String selectedAttachmentType;

	/** ... TODO Javadoc ... */
	private String title;

	/**
	 * 
	 * @param parentShell
	 * @param launchApps
	 */
	public LaunchApplicationDialog(Shell parentShell, String title, String message, ArrayList<AttachmentType> launchApps) {
		super(parentShell);
		this.launchApps = launchApps;
		this.title = title;
		this.message = message;
	}

	/**
	 * 
	 * @param listener
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(listener);

	}

	/**
	 * ... TODO Javadoc ...
	 */
	public void create() {
		super.create();
		setTitle(title);
		setMessage(message);
		setTitleImage(CommonImages.getImage(CommonImages.WIZBAN_ATTACHMENT));
	}

	/**
	 * 
	 */
	protected Control createDialogArea(Composite parent) {
		final Composite outerContainer = (Composite) super.createDialogArea(parent);

		Composite container = new Composite(outerContainer, SWT.NONE);
		GridLayout containerLayout = new GridLayout();
		containerLayout.marginTop = containerLayout.marginBottom = containerLayout.marginLeft = containerLayout.marginRight = 10;
		containerLayout.verticalSpacing = 10;
		container.setLayout(containerLayout);
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		initializeDialogUnits(container);

		Label lblInstructions = new Label(container, SWT.WRAP);
		GridData gd_lblInstructions = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
		gd_lblInstructions.widthHint = 430;
		lblInstructions.setLayoutData(gd_lblInstructions);
		lblInstructions
				.setText("There is more than one application found that is capable of opening the selected attachment, please select which application you wish to use to open the attachment.");

		list = new List(container, SWT.BORDER);
		list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		ListViewer listViewer = new ListViewer(list);
		listViewer.setContentProvider(new AttachmentTypeContentProvider());
		listViewer.setLabelProvider(new AttachmentTypeLabelProvider());
		listViewer.setInput(launchApps);

		initDataBindings();
		initBindingSupport();

		return outerContainer;
	}

	/**
	 * 
	 * @return
	 */
	public PropertyChangeSupport getPropertyChangeSupport() {
		return propertyChangeSupport;
	}

	/**
	 * @return the selectedAttachment
	 */
	public String getSelectedAttachmentType() {
		return selectedAttachmentType;
	}

	/**
	 * <p>
	 * <b>Initialises the binding support for the dialog.</b><br/>
	 * This method initialises a <code>TitleAreaDialogSupport</code> class which
	 * links an errors that are created from the data binding code to error
	 * messages that are displayed in the title area of the dialog. In order to
	 * manage the enablement of the OK button we need to subclass the validation
	 * message provider so that we can add code that either enables or disables
	 * the button based on whether there are any errors.
	 * </p>
	 */
	private void initBindingSupport() {
		TitleAreaDialogSupport tads = TitleAreaDialogSupport.create(this, bindingContext);
		tads.setValidationMessageProvider(new ValidationMessageProvider() {
			public String getMessage(ValidationStatusProvider statusProvider) {
				if (statusProvider == null) {
					return message;
				}
				return super.getMessage(statusProvider);
			}

			public int getMessageType(ValidationStatusProvider statusProvider) {
				int type = super.getMessageType(statusProvider);
				if (getButton(IDialogConstants.OK_ID) != null) {
					getButton(IDialogConstants.OK_ID).setEnabled(type != IMessageProvider.ERROR);
				}
				return type;
			}
		});
	}

	/**
	 * 
	 */
	private void initDataBindings() {
		bindingContext = new DataBindingContext();

		IObservableValue typeObserveWidget = WidgetProperties.selection().observe(list);
		IObservableValue typeObserveValue = BeanProperties.value(LaunchApplicationDialog.class, "selectedAttachmentType").observe(this);
		bindingContext.bindValue(typeObserveWidget, typeObserveValue, null, null);
	}

	/**
	 * 
	 * @param listener
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);

	}

	/**
	 * @param selectedAttachment
	 *            the selectedAttachment to set
	 */
	public void setSelectedAttachmentType(String selectedAttachmentType) {
		this.selectedAttachmentType = selectedAttachmentType;
	}

}
